home *** CD-ROM | disk | FTP | other *** search
-
- //////////////////////////////////////////////////////////////////////////
- //
- // cppscan.c
- //
- // Copyright 1997 by James Iuliano
- //
- // Permission granted to use this program for development
- // of Lemmy VI editor syntax highlight plug-ins. Permission
- // for any other use must be obtained by James Iuliano.
- //
- //////////////////////////////////////////////////////////////////////////
-
- #include <windows.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "syntax.h"
- #include "cppscan.h"
- #include "dlgmacro.h"
-
-
- #define C_KEYWORD 0x01
- #define CPP_KEYWORD 0x02
-
- typedef struct cpp_extra_struct
- {
- short keywords;
- BOOL cpp_comments;
- }
- cpp_extra_struct;
-
- static parse_context_type *lpPC;
- static cpp_extra_struct *cpp;
-
- //
- // Private routines (forward referenced)...
- //
- // The scan_... routines will typically set the lpPC->ParseState member
- // based on what they find...
- //
- static int isodigit(char digit);
- static BOOL test_continuation(char *next_token);
- static BOOL scan_comment_conditions(char *text);
- static char *scan_from_preprocessor(char *next_token, parse_context_type *lpPC);
- static char *scan_comment(char *next_token, parse_context_type *lpPC);
- static char *scan_string(char *next_token, parse_context_type *lpPC);
- static int is_c_keyword(char *token);
-
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // API Definitions...
- //
- ////////////////////////////////////////////////////////////////////////
-
- DllExport(char *) ParseEngineName()
- {
- static char name[32];
-
- strcpy( name, "C/C++ Parser" );
- return(name);
- }
-
-
-
- //
- // ..stubs..
- //
- DllExport(short) ParsePropertiesAvailable()
- {
- return(TRUE);
- }
-
-
-
- long FAR PASCAL PropertiesDialogProc(HWND hWnd, WORD iMessage, WORD wParam, DWORD lParam)
- {
- switch (iMessage)
- {
- case WM_INITDIALOG:
- SETCK(IDC_DO_CPP, (cpp->keywords & CPP_KEYWORD));
- SETCK(IDC_DO_CPP_COMMENTS, cpp->cpp_comments);
- return TRUE;
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- case IDOK:
- if ( GETCK(IDC_DO_CPP) )
- cpp->keywords = C_KEYWORD | CPP_KEYWORD;
- else
- cpp->keywords = C_KEYWORD;
-
- cpp->cpp_comments = GETCK(IDC_DO_CPP_COMMENTS);
-
- SaveEngineInfoInt("CPPDoCPPKeywords", (cpp->keywords & CPP_KEYWORD));
- SaveEngineInfoInt("CPPDoCPPComments", cpp->cpp_comments);
-
- EndDialog(hWnd, 0);
- return(TRUE);
- break;
- case IDCANCEL:
- EndDialog(hWnd, 0);
- return(TRUE);
- break;
- }
- break;
- }
- return(0L);
- }
-
-
-
-
-
-
- static void show_system_error()
- {
- LPTSTR lpMsg;
- DWORD last_error;
-
- last_error = GetLastError();
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsg, 0, NULL);
- MessageBox(GetActiveWindow(), lpMsg, "LoadResource", MB_ICONEXCLAMATION);
- LocalFree(lpMsg);
- }
-
-
-
-
-
- DllExport(short) ParseProperties( parse_context_type *lpPCLocal )
- {
- DLGPROC lpfnDialogProc;
- int dlg_return;
- static HANDLE hDialog;
- HINSTANCE hInst;
- HINSTANCE hLib;
- HGLOBAL prop_hGlbl;
- HWND hWnd;
- HRSRC dialog_resource;
-
- lpPC = lpPCLocal;
- cpp = (cpp_extra_struct *)lpPC->lpExtra;
- hWnd = GetActiveWindow();
- hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
- hLib = lpPC->hLibrary;
-
- lpfnDialogProc = (DLGPROC)MakeProcInstance((FARPROC)PropertiesDialogProc, hInst);
- if ( lpfnDialogProc == NULL )
- {
- cpp = NULL;
- lpPC = NULL;
-
- return(FALSE);
- }
-
- dialog_resource = FindResource(hLib, "PROPERTIES", RT_DIALOG);
- if ( dialog_resource != NULL )
- {
- prop_hGlbl = LoadResource(hLib, dialog_resource);
- if ( prop_hGlbl != NULL )
- {
- dlg_return = DialogBoxIndirect( hInst, (LPDLGTEMPLATE)prop_hGlbl,
- hWnd, lpfnDialogProc );
- }
- else
- {
- show_system_error();
- dlg_return = -1;
- }
- }
- else
- {
- show_system_error();
- dlg_return = -1;
- }
-
- if ( dlg_return < 0 )
- {
- MessageBox( hWnd, "Failed to open property dialog.", "C/C++ Properties", MB_OK );
- }
-
- FreeProcInstance((FARPROC)lpfnDialogProc);
- cpp = NULL;
- lpPC = NULL;
-
- return(TRUE);
- }
-
-
-
- DllExport(short) ParseCustomKeywordsSupported() { return(0); }
-
-
-
-
-
-
- DllExport(short) ParseLoadCustomTokens( parse_context_type *lpPC )
- {
- //LoadTokenInfo( &(lpPC->CustomToken[0]) );
- return(0);
- }
-
-
-
-
-
-
- DllExport(short) ParseSaveCustomTokens( parse_context_type *lpPC )
- {
- //SaveTokenInfo( &(lpPC->CustomToken[0]) );
- return(0);
- }
-
-
-
-
- DllExport(short) ParseConstructor( parse_context_type *lpPC )
- {
- lpPC->lpExtra = (void *)malloc(sizeof(cpp_extra_struct));
- cpp = (cpp_extra_struct *)lpPC->lpExtra;
-
- cpp->cpp_comments = (BOOL)LoadEngineInfoInt("CPPDoCPPComments", TRUE);
-
- cpp->keywords = C_KEYWORD;
- if ( (BOOL)LoadEngineInfoInt("CPPDoCPPKeywords", TRUE) )
- cpp->keywords |= CPP_KEYWORD;
-
- lpPC->CustomTokenMax = 0;
-
- cpp = NULL;
-
- return(0);
- }
-
-
-
-
- DllExport(short) ParseDestructor( parse_context_type *lpPC )
- {
- free( lpPC->lpExtra );
- lpPC->lpExtra = NULL;
-
- return(0);
- }
-
-
-
- DllExport(short) ParseInitRedraw( parse_context_type *lpPC )
- {
- return(0);
- }
-
-
-
- DllExport(short) ParseInitParser( parse_context_type *lpPC )
- {
- return(0);
- }
-
-
-
-
- DllExport(short) ParseBackscan( parse_context_type *lpPC )
- {
- char *text;
-
- text = lpPC->lpParseText;
-
- if ( (strlen( text ) >= 2) &&
- ( text[strlen(text)-1] == '\\') )
- {
- return(0);
- }
-
- if ( !scan_comment_conditions(text) )
- {
- return(0);
- }
-
- lpPC->FinishBackscan = TRUE;
- return(0);
- }
-
-
-
-
-
- DllExport(short) ParseToken( parse_context_type *lpPC )
- {
- char *next_token;
- char *tmp_pointer;
- char akeyword[15]; //
- int flag_period = FALSE; // Flag for decimal point on decimal numbers
- int flag_exp = FALSE; // Flag for exponent (E|e) on decimal numbers
-
- cpp = (cpp_extra_struct *)lpPC->lpExtra;
-
- next_token = SkipWhiteSpace( lpPC->lpParseText );
-
- if ( (lpPC->ParseState != st_fresh_start) &&
- (lpPC->PreviousLine < lpPC->ScanningLine) )
- {
- switch ( lpPC->ScannedToken )
- {
- case tk_string:
- next_token = scan_string(next_token, lpPC);
-
- lpPC->lpParseText = SkipWhiteSpace( next_token );
-
- return(0);
- break;
- case tk_comment:
- next_token = scan_comment(next_token, lpPC);
-
- lpPC->lpParseText = SkipWhiteSpace( next_token );
-
- return(0);
- break;
- case tk_preprocessor:
- next_token = scan_from_preprocessor(next_token, lpPC);
-
- lpPC->lpParseText = next_token;
- lpPC->ScannedToken = tk_preprocessor;
-
- return(0);
- break;
- }
- }
-
- //
- // Check for preprocessor first...
- //
- if ( (lpPC->ScanColumn == 0) && (*next_token == '#') )
- {
- next_token = scan_from_preprocessor(next_token, lpPC);
-
- lpPC->lpParseText = next_token;
- lpPC->ScannedToken = tk_preprocessor;
-
- return(0);
- }
-
- //
- // '.' could be either struct or float - advance over the period if float
- //
- if ( *next_token == '.' && isdigit( *(next_token + 1) ) )
- {
- flag_period = TRUE;
- next_token++;
- }
-
- //
- // '_' is really considered alpha
- // If punctuation of some type...figure it out
- //
- if ( ispunct( *next_token ) && *next_token != '_' )
- {
- // If next token is of STRING type
- if ( *next_token == '"' )
- {
- next_token++;
-
- next_token = scan_string(next_token, lpPC);
-
- lpPC->lpParseText = SkipWhiteSpace( next_token );
- lpPC->ScannedToken = tk_string;
-
- return(0);
- }
-
- // If next token is a single CHAR STRING type
- else if ( *next_token == '\'' )
- {
- next_token++;
-
- while ( (*next_token != '\'') && *next_token )
- {
- if ( *next_token == '\\' )
- next_token++;
-
- next_token++;
- }
-
- //(*aline) = remove_white_space( ++next_token );
- if ( *next_token ) ++next_token;
-
- lpPC->lpParseText = SkipWhiteSpace( next_token );
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_char;
-
- return(0);
- }
-
- // If next token is of COMMENT (C++ variety) type
- else if ( *next_token == '/' && *(next_token + 1) == '/' && cpp->cpp_comments )
- {
- lpPC->lpParseText = &lpPC->lpParseText[strlen(lpPC->lpParseText)]; // null terminator
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_comment;
-
- return(0);
- }
-
- // If next token is of COMMENT (C variety) type
- else if ( *next_token == '/' && *(next_token + 1) == '*' )
- {
- next_token += 2;
-
- next_token = scan_comment(next_token, lpPC);
-
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ScannedToken = tk_comment;
-
- return(0);
- }
-
- //
- // Default...
- //
- else
- {
- ++(lpPC->lpParseText);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(0);
- }
- }
-
- // Number of some type ... decimal, hex, or octal
- else if ( isdigit( *next_token ) )
- {
- // Hex
- if ( *next_token == '0' && *(next_token + 1) =='x' && !flag_period )
- {
- next_token += 2;
-
- if ( !isxdigit( *next_token ))
- {
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ScannedToken = tk_none;
- lpPC->ParseState = st_fresh_start;
- return(-1);
- }
-
- while ( isxdigit( *next_token ) && *next_token )
- {
- next_token++;
- }
-
- if ( ((tolower( *next_token ) == 'l') || (tolower( *next_token ) == 'u' )) &&
- !isalnum( *(next_token + 1) )
- )
- {
- next_token += 1;
- }
-
- if ( isalpha( *next_token ) )
- {
- lpPC->lpParseText = SkipWhiteSpace(++next_token);
- lpPC->ScannedToken = tk_none;
- lpPC->ParseState = st_fresh_start;
- return(-1);
- }
-
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_number;
- }
-
- // Octal..
- else if ( *next_token == '0' && isdigit( *(next_token + 1) ) && !flag_period )
- {
- next_token += 1;
-
- while ( isodigit( *next_token ) && *next_token )
- {
- next_token++;
- }
-
- if ( ((tolower( *next_token ) == 'l') || (tolower( *next_token ) == 'u' )) &&
- !isalnum( *(next_token + 1) )
- )
- {
- next_token += 1;
- }
-
- if ( isalnum( *next_token ) )
- {
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(-1);
- }
-
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_number;
- return(0);
- }
- else
- {
- Decimal:
- while ( isdigit( *next_token ) && *next_token )
- {
- next_token++;
- }
-
- //
- // decimal point.
- //
- if ( *next_token == '.' )
- {
- next_token++;
-
- if ( flag_period )
- {
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(-1);
- }
- else
- {
- flag_period = TRUE;
- goto Decimal;
- }
- }
-
- //
- // exponential form...
- //
- if ( tolower( *next_token ) == 'e' )
- {
- next_token++;
-
- if ( flag_exp )
- {
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(-1);
- }
- else
- {
- flag_exp = TRUE;
-
- if ( *next_token == '+' || *next_token == '-' )
- {
- next_token++;
- }
-
- if ( !isdigit( *next_token ) )
- {
- lpPC->lpParseText = SkipWhiteSpace(++next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(-1);
- }
-
- goto Decimal;
- }
- }
-
- if ( flag_exp || flag_period )
- {
- if ( (( tolower( *next_token ) == 'l' ) ||
- ( tolower( *next_token ) == 'f' )) && !isalnum( *(next_token + 1) )
- )
- {
- next_token += 1;
- }
- }
-
- else
- {
- if ( (( tolower( *next_token ) == 'l' ) ||
- ( tolower( *next_token ) == 'u' )) && !isalnum( *(next_token + 1) )
- )
- {
- next_token += 1;
- }
- }
-
- if ( isalpha( *next_token ) )
- {
- lpPC->lpParseText = SkipWhiteSpace(++next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(-1);
- }
-
- lpPC->lpParseText = SkipWhiteSpace(next_token);
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_number;
- return(0);
- }
- }
-
- // Keywords...
- else
- {
- tmp_pointer = next_token;
-
- //
- // Suck it in...
- //
- while (( isalnum( *tmp_pointer ) || *tmp_pointer == '_' ) && *tmp_pointer ) {
- tmp_pointer++;
- }
-
- lpPC->lpParseText = SkipWhiteSpace(tmp_pointer);
-
- // So it doesn't crap out for long non-keywords
- if ( (tmp_pointer - next_token) > 10 )
- {
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(0);
- }
-
- strncpy( akeyword, next_token, (tmp_pointer - next_token) );
- akeyword[ tmp_pointer - next_token ] = '\0';
-
- if ( is_c_keyword( akeyword ) )
- {
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_keyword;
- return(0);
- }
-
- lpPC->ParseState = st_fresh_start;
- lpPC->ScannedToken = tk_none;
- return(0);
- }
- }
-
-
-
-
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Internal Routines...
- //
- ////////////////////////////////////////////////////////////////////////
-
- static int isodigit( char digit )
- {
- if ( digit >= '0' && digit <= '7' )
- return( TRUE );
-
- return( FALSE );
- }
-
-
-
-
- static BOOL test_continuation(char *next_token)
- {
- return( (*next_token) && (*next_token == '\\') && !*(next_token+1) );
- }
-
-
-
-
-
- static BOOL scan_comment_conditions(char *text)
- {
- char *scan_text, *sptr;
- char *close_comment;
- char *open_comment;
- char *quote;
- //char *pound;
-
- if ( text == NULL ) return(FALSE);
-
- sptr = scan_text = (char *)malloc(strlen(text)+1);
- strcpy(scan_text,text);
-
- close_comment = strstr(scan_text, "*/");
- open_comment = strstr(scan_text, "/*");
- quote = strstr(scan_text, "\"");
-
- if ( !quote )
- if ( open_comment || close_comment )
- {
- free(sptr);
- return(TRUE);
- }
-
- free(sptr);
-
- return(FALSE);
- }
-
-
-
-
- static char *scan_from_preprocessor( char *next_token,
- parse_context_type *lpPC )
- {
- while ( *next_token )
- {
- if ( (*next_token == '/') &&
- (*(next_token + 1) == '/') )
- break;
-
- if ( (*next_token == '/') &&
- (*(next_token + 1) == '*') )
- break;
-
- if ( test_continuation(next_token) )
- {
- lpPC->ParseState = st_continue_previous;
- next_token++;
- break;
- }
-
- lpPC->ParseState = st_fresh_start;
- next_token++;
- }
-
- return(next_token);
- }
-
-
-
-
-
- static char *scan_comment(char *next_token, parse_context_type *lpPC)
- {
- BOOL done;
-
- done = FALSE;
- while ( !done )
- {
- while ( (*next_token != '/') && *next_token )
- {
- next_token++;
- }
-
- if ( *(next_token - 1) == '*' || !(*next_token) )
- {
- if ( !(*next_token) )
- lpPC->ParseState = st_continue_comment;
- else
- lpPC->ParseState = st_fresh_start;
-
- done = TRUE;
- }
-
- if ( *next_token ) next_token++;
- }
-
- return(next_token);
- }
-
-
-
-
-
- static char *scan_string(char *next_token, parse_context_type *lpPC)
- {
- while ( (*next_token != '"') && *next_token )
- {
- if ( test_continuation(next_token) )
- {
- lpPC->ParseState = st_continue_previous;
- ++next_token;
- break;
- }
-
- lpPC->ParseState = st_fresh_start;
- if ( *next_token == '\\' ) next_token++;
- next_token++;
- }
-
- if ( *next_token ) ++next_token;
-
- return(next_token);
- }
-
-
-
-
- //
- // Keyword stuff...
- //
- static int is_c_keyword( char *token )
- {
- typedef struct keyword_type
- {
- char *kw;
- BOOL lang;
- }
- keyword_type;
-
- static keyword_type keywords_2[] =
- {
- "do", C_KEYWORD|CPP_KEYWORD, /* C */
- "if", C_KEYWORD|CPP_KEYWORD, /* C */
- NULL, NULL
- };
-
- static keyword_type keywords_3[] =
- {
- "for", C_KEYWORD|CPP_KEYWORD, /* C */
- "int", C_KEYWORD|CPP_KEYWORD, /* C */
- "asm", CPP_KEYWORD, /* C++?*/
- "new", CPP_KEYWORD, /* C++ */
- "try", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- static keyword_type keywords_4[] = {
- "auto", C_KEYWORD|CPP_KEYWORD, /* C */
- "case", C_KEYWORD|CPP_KEYWORD, /* C */
- "char", C_KEYWORD|CPP_KEYWORD, /* C */
- "else", C_KEYWORD|CPP_KEYWORD, /* C */
- "enum", C_KEYWORD|CPP_KEYWORD, /* C */
- "goto", C_KEYWORD|CPP_KEYWORD, /* C */
- "long", C_KEYWORD|CPP_KEYWORD, /* C */
- "void", C_KEYWORD|CPP_KEYWORD, /* C */
- "bool", CPP_KEYWORD, /* New as of GCC 2.6.0 */
- "this", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- static keyword_type keywords_5[] = {
- "break", C_KEYWORD|CPP_KEYWORD, /* C */
- "const", C_KEYWORD|CPP_KEYWORD, /* C */
- "float", C_KEYWORD|CPP_KEYWORD, /* C */
- "short", C_KEYWORD|CPP_KEYWORD, /* C */
- "union", C_KEYWORD|CPP_KEYWORD, /* C */
- "while", C_KEYWORD|CPP_KEYWORD, /* C */
- "catch", CPP_KEYWORD, /* C++ */
- "class", CPP_KEYWORD, /* C++ */
- "throw", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- static keyword_type keywords_6[] = {
- "double", C_KEYWORD|CPP_KEYWORD, /* C */
- "extern", C_KEYWORD|CPP_KEYWORD, /* C */
- "return", C_KEYWORD|CPP_KEYWORD, /* C */
- "signed", C_KEYWORD|CPP_KEYWORD, /* C */
- "sizeof", C_KEYWORD|CPP_KEYWORD, /* C */
- "static", C_KEYWORD|CPP_KEYWORD, /* C */
- "struct", C_KEYWORD|CPP_KEYWORD, /* C */
- "switch", C_KEYWORD|CPP_KEYWORD, /* C */
- "delete", CPP_KEYWORD, /* C++ */
- "friend", CPP_KEYWORD, /* C++ */
- "inline", CPP_KEYWORD, /* C++ */
- "public", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- static keyword_type keywords_7[] = {
- "default", C_KEYWORD|CPP_KEYWORD, /* C */
- "typedef", C_KEYWORD|CPP_KEYWORD, /* C */
- "private", CPP_KEYWORD, /* C++ */
- "virtual", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- static keyword_type keywords_8[] = {
- "continue", C_KEYWORD|CPP_KEYWORD, /* C */
- "register", C_KEYWORD|CPP_KEYWORD, /* C */
- "unsigned", C_KEYWORD|CPP_KEYWORD, /* C */
- "volatile", C_KEYWORD|CPP_KEYWORD, /* C */
- "operator", CPP_KEYWORD, /* C++ */
- "template", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- static keyword_type keywords_9[] = {
- "protected", CPP_KEYWORD, /* C++ */
- NULL, NULL
- };
-
- int count = 0;
- keyword_type * keywords;
-
- switch ( strlen( token ) ) {
- case 2: keywords = keywords_2;
- break;
- case 3: keywords = keywords_3;
- break;
- case 4: keywords = keywords_4;
- break;
- case 5: keywords = keywords_5;
- break;
- case 6: keywords = keywords_6;
- break;
- case 7: keywords = keywords_7;
- break;
- case 8: keywords = keywords_8;
- break;
- case 9: keywords = keywords_9;
- break;
- default: return( FALSE );
- }
-
- for ( ; keywords[ count ].kw != NULL; count++ ) {
- if ( strcmp( keywords[ count ].kw, token ) == 0 &&
- (keywords[ count ].lang & cpp->keywords) )
- return( TRUE );
- }
-
- return( FALSE );
-
- }
-